/**
 * @className ByteUtil
 * @description 字节流处理工具类
 * @author stydm
 * @date 2020/7/7 8:40
 */

package com.jiufengxinxi.ts.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;

public class ByteUtil {
    //	/**
//	 * 字节转换为十六进制字符串
//	 *
//	 * @param value byte,字节
//	 * @return 十六进制字符串
//	 * @author Awens
//	 * @version 1.0
//	 */
//	@Deprecated
//	public static String byteToHexStr(byte value)
//	{
//		String result = "";
//		int iv = value & 0xFF;
//		;
//		result = Integer.toHexString(iv).toUpperCase();
//		if (result.length() == 1)
//		{
//			result = '0' + result;
//		}
//		return result;
//	}

    /**
     *
     */
    public static String byteToHexString(byte data) {
        return bytesToHexString(new byte[]{data}, false);
    }

    /**
     *
     */
    public static String shortToHexString(short data) {
        return bytesToHexString(shortToByte2(data), false);
    }


    /**
     *
     */
    public static String intToHexString(int data) {
        return bytesToHexString(intToByte4(data), false);
    }

    /**
     *
     */
    public static String longToHexString(long data) {
        return bytesToHexString(longToByte8(data), false);
    }

    /**
     *
     */
    public static String bytesToHexString(byte[] value, boolean isReverse) {
        return bytesToHexString(value, 0, value.length, isReverse);
    }

    /**
     * 将字节数组转换成16进制字符串表示。
     *
     * @param value     byte{],字节数组
     * @param isReverse boolean,是否反转字节数组输出，即后进先出
     * @return 十六进制字符串
     * @author Awens
     * @version 1.0
     */
    public static String bytesToHexString(byte[] value, int start, int length, boolean isReverse) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (value == null) {
            return null;
        }
        if (value.length == 0) {
            return "";
        }

        int end = start + length;
        if (isReverse) {
            for (int i = end - 1; i >= start; i--) {
                int v = value[i] & 0xFF;
                stringBuilder.append(StringUtils.leftPad(Integer.toHexString(v), 2, '0'));
            }
        } else {
            for (int i = start; i < end; i++) {
                int v = value[i] & 0xFF;
                stringBuilder.append(StringUtils.leftPad(Integer.toHexString(v), 2, '0'));
            }
        }
        return stringBuilder.toString().toUpperCase();
    }

    public static Long byteArrayToLong(byte[] src, int begin, int length) {
        if (src == null) {
            return null;
        }

        byte[] dest = new byte[]{0, 0, 0, 0, 0, 0, 0, 0};
        int destPos = length > dest.length ? 0 : dest.length - length;
        int indeedLength = Math.min(length, dest.length);
        System.arraycopy(src, begin, dest, destPos, indeedLength);

        return byte8ToLong(dest);
    }

    /**
     * 将十六进制的字节字符串转换为字节数组
     *
     * @param value     string to convert
     * @param isReverse 生成的数组是否反向排序，限字节数组从高字节开始排
     * @return byte[], 字节数组
     * @author Awens
     * @version 1.0
     */
    public static byte[] bytesFromHexStr(String value, boolean isReverse) {
        String s = value.toUpperCase();
        if (s.length() % 2 != 0) {
            s = "0" + value;
        }
        byte[] b = new byte[s.length() / 2];
        int vi;
        int hexStartIndex, hexEndIndex;

        int bytesLength = b.length;
        for (int i = 0; i < bytesLength; ++i) {
            // < 高字节在前
            if (isReverse) {
                hexStartIndex = (bytesLength - 1 - i) * 2;
                hexEndIndex = (bytesLength - i) * 2;
            }
            // > 高字节在前
            // < 低字节在前
            else {
                hexStartIndex = i * 2;
                hexEndIndex = (i + 1) * 2;
            }
            // > 低字节在前
            vi = Integer.valueOf(s.substring(hexStartIndex, hexEndIndex), 16);
            b[i] = (byte) vi;
        }
        return b;
    }

    public static String stringFromHexStr(String hex, boolean isReverse) {
        byte[] bytes = bytesFromHexStr(hex, isReverse);
        if (bytes == null) {
            return null;
        } else {
            return new String(bytes);
        }
    }

    public static String stringFromHexStr(String hex, boolean isReverse, String encoding) throws UnsupportedEncodingException {
        byte[] bytes = bytesFromHexStr(hex, isReverse);
        if (bytes == null) {
            return null;
        } else {
            return new String(bytes, encoding);
        }
    }

    //byte 与 int 的相互转换
    public static byte intToByte(int x) {
        return (byte) x;
    }

    public static int byteToInt(byte b) {
        //Java 总是把 byte 当做有符处理；我们可以通过将其和 0xFF 进行二进制与得到它的无符值
        return b & 0xFF;
    }

    /**
     * 低位的4个字节转整型
     *
     * @param src
     * @return
     */
    public static Integer byteToInt(byte[] src) {
        if (src == null) {
            return null;
        }

        byte[] dest = new byte[]{0, 0, 0, 0};
        int srcPos = src.length > dest.length ? src.length - dest.length : 0;
        int destPos = src.length > dest.length ? 0 : dest.length - src.length;
        int length = Math.min(src.length, dest.length);
        System.arraycopy(src, srcPos, dest, destPos, length);

        return byte4ToInt(dest);
    }

    //byte 数组与 int 的相互转换
    public static int byteArrayToInt(byte[] b) {
        return b[3] & 0xFF |
                (b[2] & 0xFF) << 8 |
                (b[1] & 0xFF) << 16 |
                (b[0] & 0xFF) << 24;
    }

    public static Integer byteArrayToInt(byte[] src, int begin, int length) {
        if (src == null) {
            return null;
        }

        byte[] dest = new byte[]{0, 0, 0, 0};
        int destPos = length > dest.length ? 0 : dest.length - length;
        int indeedLength = Math.min(length, dest.length);
        System.arraycopy(src, begin, dest, destPos, indeedLength);

        return byte4ToInt(dest);
    }

    public static String byteToUtf8String(byte[] src) {
        return ByteUtil.byteToString(src, "utf-8");
    }

    public static String byteToUtf8String(byte[] src, int begin, int length) {
        if (src == null) {
            return null;
        }

        byte[] dest = new byte[length];
        System.arraycopy(src, begin, dest, 0, length);
        return byteToUtf8String(dest);
    }


    public static String byteToString(byte[] src, String charset) {
        try {
            String result = new String(src, charset);
            result = result.replaceAll("[\\x00-\\x1F]|\\x7F", "");// 移除控制字符
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] intToByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    //byte 数组与 long 的相互转换
    public static long byteArrayTolong(byte[] b) {
        return
                b[7] & 0xFF |
                        (b[6] & 0xFF) << 8 |
                        (b[5] & 0xFF) << 16 |
                        (b[4] & 0xFF) << 24 |
                        (b[3] & 0xFF) << 32 |
                        (b[2] & 0xFF) << 40 |
                        (b[1] & 0xFF) << 48 |
                        (b[0] & 0xFF) << 56;
    }

    public static byte[] longToByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 56) & 0xFF),
                (byte) ((a >> 48) & 0xFF),
                (byte) ((a >> 40) & 0xFF),
                (byte) ((a >> 32) & 0xFF),
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    /**
     * 将4个byte数字组成的数组合并为一个float数.
     *
     * @param arr
     * @return
     */
    public static float byte4ToFloat(byte[] arr) {
        if (arr == null || arr.length != 4) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是4位!");
        }
        int i = byte4ToInt(arr);
        return Float.intBitsToFloat(i);
    }

    /**
     * 将一个float数字转换为4个byte数字组成的数组.
     *
     * @param f
     * @return
     */
    public static byte[] floatToByte4(float f) {
        int i = Float.floatToIntBits(f);
        return intToByte4(i);
    }

    /**
     * 将八个byte数字组成的数组转换为一个double数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static double byte8ToDouble(byte[] arr) {
        if (arr == null || arr.length != 8) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是8位!");
        }
        long l = byte8ToLong(arr);
        return Double.longBitsToDouble(l);
    }

    /**
     * 将一个double数字转换为8个byte数字组成的数组.
     *
     * @param i
     * @return
     */
    public static byte[] doubleToByte8(double i) {
        long j = Double.doubleToLongBits(i);
        return longToByte8(j);
    }

    /**
     * 将一个char字符转换为两个byte数字转换为的数组.
     * </pre>
     *
     * @param c
     * @return
     */
    public static byte[] charToByte2(char c) {
        byte[] arr = new byte[2];
        arr[0] = (byte) (c >> 8);
        arr[1] = (byte) (c & 0xff);
        return arr;
    }

    /**
     * 将2个byte数字组成的数组转换为一个char字符.
     *
     * @param arr
     * @return
     */
    public static char byte2ToChar(byte[] arr) {
        if (arr == null || arr.length != 2) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是2位!");
        }
        return (char) (((char) (arr[0] << 8)) | ((char) arr[1]));
    }

    /**
     * 将一个16位的short转换为长度为2的8位byte数组.*
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte2(Short s) {
        byte[] arr = new byte[2];
        arr[0] = (byte) (s >> 8);
        arr[1] = (byte) (s & 0xff);
        return arr;
    }

    /**
     * 长度为2的8位byte数组转换为一个16位short数字.
     *
     * @param arr
     * @return
     */
    public static short byte2ToShort(byte[] arr) {
        if (arr != null && arr.length != 2) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是2位!");
        }
        return (short) (((short) arr[0] << 8) | ((short) arr[1] & 0xff));
    }

    /**
     * 长度为2的8位byte数组转换为一个16位short数字.
     *
     * @param arr
     * @return
     */
    public static short byte2ToShort(byte[] arr, int offset) {
        return (short) (
                ((short) arr[offset] << 8) | ((short) arr[offset + 1] & 0xff)
        );
    }

    /**
     * 长度为2的8位byte数组转换为一个16位short数字.
     *
     * @param isReverse true:小端法，false：大端法
     * @author zoneyu 17-7-7
     */
    public static short byte2ToShort(byte[] arr, int offset, boolean isReverse) {
        if (!isReverse) {
            return (short) (
                    ((short) arr[offset] << 8) | ((short) arr[offset + 1] & 0xff)
            );
        } else {
            return (short) (
                    ((short) arr[offset + 1] << 8) | ((short) arr[offset] & 0xff)
            );
        }

    }

    /**
     * 将short转换为长度为16的byte数组.
     * 实际上每个8位byte只存储了一个0或1的数字
     * 比较浪费.
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte16(short s) {
        byte[] arr = new byte[16];
        for (int i = 15; i >= 0; i--) {
            arr[i] = (byte) (s & 1);
            s >>= 1;
        }
        return arr;
    }

    public static short byte16ToShort(byte[] arr) {
        if (arr == null || arr.length != 16) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度为16!");
        }
        short sum = 0;
        for (int i = 0; i < 16; ++i) {
            sum |= (arr[i] << (15 - i));
        }
        return sum;
    }

    /**
     * 将32位int转换为由四个8位byte数字.
     *
     * @param sum
     * @return
     */
    public static byte[] intToByte4(int sum) {
        byte[] arr = new byte[4];
        arr[0] = (byte) (sum >> 24);
        arr[1] = (byte) (sum >> 16);
        arr[2] = (byte) (sum >> 8);
        arr[3] = (byte) (sum & 0xff);
        return arr;
    }

    /**
     * 将长度为4的8位byte数组转换为32位int.
     *
     * @param arr
     * @return
     */
    public static int byte4ToInt(byte[] arr) {
        if (arr == null || arr.length != 4) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是4位!");
        }
        return byte4ToInt(arr, 0, false);
    }

    /**
     * 将长度为4的8位byte数组转换为32位int.
     *
     * @param arr
     * @return
     */
    public static int byte4ToInt(byte[] arr, int offset) {
        return byte4ToInt(arr, offset, false);
    }

    /**
     * 将长度为4的8位byte数组转换为32位int.
     *
     * @param arr
     * @return
     */
    public static int byte4ToInt(byte[] arr, int offset, boolean isReverse) {
        if (isReverse == false) {
            return (int) (
                    ((arr[offset] & 0xff) << 24) |
                            ((arr[offset + 1] & 0xff) << 16) |
                            ((arr[offset + 2] & 0xff) << 8) |
                            ((arr[offset + 3] & 0xff))
            );
        } else {
            return (int) (
                    ((arr[offset + 3] & 0xff) << 24) |
                            ((arr[offset + 2] & 0xff) << 16) |
                            ((arr[offset + 1] & 0xff) << 8) |
                            ((arr[offset] & 0xff))
            );
        }
    }

    /**
     * 将长度为3的8位byte数组转换为32位int.
     *
     * @param arr
     * @return
     */
    public static int byte3ToInt(byte[] arr, int offset) {
        return byte3ToInt(arr, offset, false);
    }

    /**
     * 将长度为3的8位byte数组转换为32位int.
     *
     * @param arr
     * @return
     */
    public static int byte3ToInt(byte[] arr, int offset, boolean isReverse) {
        if (isReverse == false) {
            return (int) (
                    ((arr[offset] & 0xff) << 16) |
                            ((arr[offset + 1] & 0xff) << 8) |
                            ((arr[offset + 2] & 0xff))
            );
        } else {
            return (int) (
                    ((arr[offset + 2] & 0xff) << 16) |
                            ((arr[offset + 1] & 0xff) << 8) |
                            ((arr[offset] & 0xff))
            );
        }
    }

    /**
     * 将长度为8的8位byte数组转换为64位long.
     * </pre>
     * <p/>
     * 0xff对应16进制,f代表1111,0xff刚好是8位 byte[]
     * arr,byte[i]&0xff刚好满足一位byte计算,不会导致数据丢失. 如果是int计算. int[] arr,arr[i]&0xffff
     *
     * @param arr
     * @return
     */
    public static long byte8ToLong(byte[] arr) {
        if (arr == null || arr.length != 8) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是8位!");
        }
        return (long) (
                ((long) (arr[0] & 0xff) << 56) |
                        ((long) (arr[1] & 0xff) << 48) |
                        ((long) (arr[2] & 0xff) << 40) |
                        ((long) (arr[3] & 0xff) << 32) |
                        ((long) (arr[4] & 0xff) << 24) |
                        ((long) (arr[5] & 0xff) << 16) |
                        ((long) (arr[6] & 0xff) << 8) |
                        ((long) (arr[7] & 0xff))
        );
    }

    /**
     * 将长度为8的8位byte数组转换为64位long.
     * </pre>
     * <p/>
     * 0xff对应16进制,f代表1111,0xff刚好是8位 byte[]
     * arr,byte[i]&0xff刚好满足一位byte计算,不会导致数据丢失. 如果是int计算. int[] arr,arr[i]&0xffff
     *
     * @param arr
     * @return
     */
    public static long byte8ToLong(byte[] arr, int offset) {
        return (long) (
                ((long) (arr[offset + 0] & 0xff) << 56) |
                        ((long) (arr[offset + 1] & 0xff) << 48) |
                        ((long) (arr[offset + 2] & 0xff) << 40) |
                        ((long) (arr[offset + 3] & 0xff) << 32) |
                        ((long) (arr[offset + 4] & 0xff) << 24) |
                        ((long) (arr[offset + 5] & 0xff) << 16) |
                        ((long) (arr[offset + 6] & 0xff) << 8) |
                        ((long) (arr[offset + 7] & 0xff))
        );
    }


    public static long hexStrToLong(String hexStr) {
        hexStr = hexStr.trim();
        if (StringUtils.isBlank(hexStr) || hexStr.length() > 16) {
            throw new IllegalArgumentException(String.format("cannot parse to long: %s", hexStr));
        }
        hexStr = StringUtils.leftPad(hexStr, 16, '0');
        byte[] bytes = ByteUtil.bytesFromHexStr(hexStr, false);
        return byte8ToLong(bytes);
    }


    /**
     * 将一个long数字转换为8个byte数组组成的数组.
     */
    public static byte[] longToByte8(long sum) {
        byte[] arr = new byte[8];
        arr[0] = (byte) (sum >> 56);
        arr[1] = (byte) (sum >> 48);
        arr[2] = (byte) (sum >> 40);
        arr[3] = (byte) (sum >> 32);
        arr[4] = (byte) (sum >> 24);
        arr[5] = (byte) (sum >> 16);
        arr[6] = (byte) (sum >> 8);
        arr[7] = (byte) (sum & 0xff);
        return arr;
    }

    /**
     * 将int转换为32位byte.
     * 实际上每个8位byte只存储了一个0或1的数字
     * 比较浪费.
     * </pre>
     *
     * @param num
     * @return
     */
    public static byte[] intToByte32(int num) {
        byte[] arr = new byte[32];
        for (int i = 31; i >= 0; i--) {
            // &1 也可以改为num&0x01,表示取最地位数字.
            arr[i] = (byte) (num & 1);
            // 右移一位.
            num >>= 1;
        }
        return arr;
    }

    /**
     * 将长度为32的byte数组转换为一个int类型值.
     * 每一个8位byte都只存储了0或1的数字.
     *
     * @param arr
     * @return
     */
    public static int byte32ToInt(byte[] arr) {
        if (arr == null || arr.length != 32) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度是32!");
        }
        int sum = 0;
        for (int i = 0; i < 32; ++i) {
            sum |= (arr[i] << (31 - i));
        }
        return sum;
    }

    /**
     * 将长度为64的byte数组转换为一个long类型值.
     * 每一个8位byte都只存储了0或1的数字.
     *
     * @param arr
     * @return
     */
    public static long byte64ToLong(byte[] arr) {
        if (arr == null || arr.length != 64) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度是64!");
        }
        long sum = 0L;
        for (int i = 0; i < 64; ++i) {
            sum |= ((long) arr[i] << (63 - i));
        }
        return sum;
    }

    /**
     * 将一个long值转换为长度为64的8位byte数组.
     * 每一个8位byte都只存储了0或1的数字.
     *
     * @param sum
     * @return
     */
    public static byte[] longToByte64(long sum) {
        byte[] arr = new byte[64];
        for (int i = 63; i >= 0; i--) {
            arr[i] = (byte) (sum & 1);
            sum >>= 1;
        }
        return arr;
    }

    //>>>>> 字节转换函数

    public static byte[] copy(byte[] src, int offset, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(src, offset, bytes, 0, length);
        return bytes;
    }

    public static void copyTo(byte[] dest, byte[] src) {
        System.arraycopy(src, 0, dest, 0, src.length);
    }

    public static void copyTo(byte[] dest, int destOffset, byte[] src, int srcOffset, int length) {
        System.arraycopy(src, srcOffset, dest, destOffset, length);
    }

    public static String fromBCD(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02X", bytes[i]));
        }
        return sb.toString();
    }

    public static boolean equals(byte[] bytes1, int offset1, int length1, byte[] bytes2, int offset2, int length2) {
        if (bytes1 == bytes2) {
            return true;
        }
        if (bytes1 == null || bytes2 == null) {
            return false;
        }
        if (length1 != length2) {
            return false;
        }
        for (int i = 0; i < length1; i++) {
            if (bytes1[offset1 + i] != bytes2[offset2 + i]) {
                return false;
            }
        }
        return true;
    }


    public static boolean equals(byte[] bytes1, byte[] bytes2) {
        return equals(bytes1, 0, bytes1.length, bytes2, 0, bytes2.length);
    }

    public static boolean equals(byte[] bytes1, int offset1, int length1, byte[] bytes2) {
        return equals(bytes1, offset1, length1, bytes2, 0, bytes2.length);
    }

    public static boolean equals(byte[] bytes1, byte[] bytes2, int offset2, int length2) {
        return equals(bytes1, 0, bytes1.length, bytes2, offset2, length2);
    }

    public static byte[] random(int length) {
        byte[] bytes = new byte[length];
        ThreadLocalRandom.current().nextBytes(bytes);
        return bytes;
    }

    public static int bytesToUnsignInt(byte[] _buf, int _offset, int _len) {
        if (_len > 4) {
            throw new RuntimeException("len: " + _len);
        }
        int res = 0;
        for (int i = 0; i < _len; i++) {
            int tmp = _buf[_offset + i] & 0xFF;
            res += tmp << 8 * (_len - i - 1);
        }
        return res;
    }

    //----------

    public static void reverse(byte[] bytes) {
        for (int i = 0; i < bytes.length / 2; i++) {
            int index1 = i;
            int index2 = bytes.length - 1 - i;
            byte byte1 = bytes[index1];
            byte byte2 = bytes[index2];
            bytes[index2] = byte1;
            bytes[index1] = byte2;
        }
    }

    public static byte getByte(byte[] bytes, int index) {
        return bytes[index];
    }

    public static void set(byte[] bytes, byte b) {
        if (bytes == null) {
            return;
        }
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = b;
        }
    }

    public static void clear(byte[] bytes) {
        set(bytes, (byte) 0);
    }

    /**
     * 从byte数组中取
     *
     * @param src
     * @param begin
     * @return
     */
    public static Date getDate(byte[] src, int begin) {
        if (src.length < begin + 7) {
            return null;
        }
        int year = ByteUtil.byteArrayToInt(src, begin, 1) + 2000;
        int month = ByteUtil.byteArrayToInt(src, begin + 1, 1);
        int date = ByteUtil.byteArrayToInt(src, begin + 2, 1);
        int hour = ByteUtil.byteArrayToInt(src, begin + 3, 1);
        int minute = ByteUtil.byteArrayToInt(src, begin + 4, 1);
        int second = ByteUtil.byteArrayToInt(src, begin + 5, 1);

        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, date, hour, minute, second);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 从指定index开始切割byte[]
     *
     * @param index
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] splitByIndex(int index, byte[] data) throws Exception {
        if (index <= data.length) {
            byte[] result = new byte[data.length - index];
            System.arraycopy(data, index, result, 0, data.length - index);
            return result;
        } else {
            throw new Exception("index 位置超过数据长度");
        }
    }

    /**
     * 从指定index开始切割byte[]
     *
     * @param start 开始索引
     * @param end   结束索引
     * @param data  数据
     * @return
     * @throws Exception
     */
    public static byte[] substring(int start, int end, byte[] data) throws Exception {
        if ((end - start) <= data.length) {
            byte[] result = new byte[end - start];
            System.arraycopy(data, start, result, 0, end - start);
            return result;
        } else {
            throw new Exception("index 位置超过数据长度");
        }
    }

    /**
     * 异或校验
     *
     * @param data
     * @return
     */
    public static byte xorVerify(byte[] data) {
        byte verify = data[0];
        for (int i = 1; i < data.length; i++) {
            verify ^= data[i];
        }
        return verify;
    }

    public static ByteBuffer put(ByteBuffer src, Object data, int length) throws Exception {
        src = put(src, length);
        if (data instanceof Byte) {
            src.put((Byte) data);
        } else if (data instanceof Short) {
            src.putShort((Short) data);
        } else if (data instanceof String) {
            put(src, ((String) data).getBytes());
        }
        return src;
    }

    public static ByteBuffer put(ByteBuffer src, int length) throws Exception {
        int available = src.remaining();
        if (available >= length) {
            return src;
        } else {
            return ByteBuffer.allocate(length - available + src.capacity());
        }
    }

    public static ByteBuffer put(ByteBuffer src, byte[] data) throws Exception {
        int available = src.remaining();
        ByteBuffer newBuffer = ByteBuffer.allocate(data.length - available + src.capacity());
        if (available >= data.length) {
            newBuffer.put(data);
        } else {
            newBuffer.put(ByteUtil.substring(0, src.position(), src.array()));
            newBuffer.put(data);
        }
        return newBuffer;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    public static byte[] DateToBcd(Date date){
        byte [] reByte = new byte[3];
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int h = calendar.get(Calendar.HOUR_OF_DAY);
        int m = calendar.get(Calendar.MINUTE);
        int s=  calendar.get(Calendar.SECOND);
        String strBCD = "";
        if(h<10){
            strBCD=strBCD+"0"+h;
        }else {
            strBCD=strBCD+h;
        }
        if(m<10){
            strBCD=strBCD+"0"+m;
        }else {
            strBCD=strBCD+m;
        }
        if(s<10){
            strBCD=strBCD+"0"+s;
        }else {
            strBCD=strBCD+s;
        }
        return Str2Bcd(strBCD);
    }

    /**
     * @功能: BCD码转为10进制串(阿拉伯数据)
     * @参数: BCD码
     * @结果: 10进制串
     */
    public static String Bcd2Str(byte[] bytes) {
        StringBuffer temp = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp
                .toString().substring(1) : temp.toString();
    }

    /**
     * @功能: 10进制串转为BCD码
     * @参数: 10进制串
     * @结果: BCD码
     */
    public static byte[] Str2Bcd(String asc) {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        byte abt[] = new byte[len];
        if (len >= 2) {
            len = len / 2;
        }
        byte bbt[] = new byte[len];
        abt = asc.getBytes();
        int j, k;
        for (int p = 0; p < asc.length() / 2; p++) {
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
                j = abt[2 * p] - '0';
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
                j = abt[2 * p] - 'a' + 0x0a;
            } else {
                j = abt[2 * p] - 'A' + 0x0a;
            }
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
                k = abt[2 * p + 1] - '0';
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
                k = abt[2 * p + 1] - 'a' + 0x0a;
            } else {
                k = abt[2 * p + 1] - 'A' + 0x0a;
            }
            int a = (j << 4) + k;
            byte b = (byte) a;
            bbt[p] = b;
        }
        return bbt;
    }

    public static byte[] getDateDiff(long gpsTime,long recTime){
        long diff = recTime - gpsTime;
        if(diff<0){
            diff=(Math.abs(diff)/1000)&8388608;
        }
        return longToByte3(diff);
    }

    public static byte[] byteMerger(byte[] byte1,byte[] byte2){
        byte[] byte3 = new byte[byte1.length + byte2.length];
        System.arraycopy(byte1,0,byte3,0,byte1.length);
        System.arraycopy(byte2,0,byte3,byte1.length,byte2.length);
        return  byte3;
    }

    /**
     * 将一个long数字转换为3个byte数组组成的数组.
     */
    public static byte[] longToByte3(long sum) {
        byte[] arr = new byte[3];
        arr[0] = (byte) (sum >> 16);
        arr[1] = (byte) (sum >> 8);
        arr[2] = (byte) (sum & 0xff);
        return arr;
    }


    /***
     * Converts a hexadecimal string into a byte array
     * @param _hex_str hexadecimal string
     * @return byte array for the hex string
     */
    public static byte[] hexToBytes(final String _hex_str) throws Exception {
        int len = _hex_str.length();
        byte[] data = new byte[len / 2 + (len % 2)];
        int n, b = 0;
        boolean high = true;
        int i = 0;

        for (int j = 0; j < len; j++) {
            char c = _hex_str.charAt(j);
            if (c == ' ')
                continue;

            n = getNibble(c);
            if (n == -1)
                throw new Exception("hexadecimal string contains non hex character " + _hex_str);    //NOI18N

            if (high) {
                b = (n & 0xf) << 4;
                high = false;
            } else {
                b += (n & 0xf);
                high = true;
                data[i++] = (byte) b;
            }
        }

        if (!high)
            throw new Exception("hexadecimal string with odd number of characters");    //NOI18N

        if (i < data.length) {
            //data = (byte[]) ArrayUtil.resizeArray(data, i);
        }

        return data;
    }


    private static int getNibble(int value) {
        if (value >= '0' && value <= '9') {
            return value - '0';
        }

        if (value >= 'a' && value <= 'f') {
            return 10 + value - 'a';
        }

        if (value >= 'A' && value <= 'F') {
            return 10 + value - 'A';
        }
        return -1;
    }

    public static void main(String[] args) {
        Date today = new Date(1570723350000l);
        Date now = new Date();

        System.out.println(getDateDiff(today.getTime(),now.getTime()));


        byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8};
//        reverse(bytes);
//        System.out.println(bytesToHexString(bytes, false));
        try {
//            System.out.println(Arrays.toString(splitByIndex(9, bytes)));
            System.out.println(Arrays.toString(substring(1, bytes.length - 1, bytes)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static long getUnsignedInt (int data){
        return data&0x0FFFFFFFFL;
    }

    public static long getUnsignedByte (byte data){
        return data&0x0FF;
    }

    public static long getUnsignedShort (short data){
        return data&0x0FFFF;
    }
}
